# include <stdio.h>
# include <stdlib.h>
# include <time.h>
# include <sys/types.h>
# include <pthread.h>
# include <semaphore.h>
# include <string.h>
# include <unistd.h>
#define BUFFER_SIZE 5

//empty  同步信号量，表示剩余空间的数量
// full 同步信号量，表示产品的数量
// mutex 互斥信号量，实现对缓冲区的互斥访问
sem_t empty, full, mutex;

typedef int buffer_item;

//缓冲区
buffer_item buffer[BUFFER_SIZE];

int in, out;

// 记录产品的id
int id = 0;

int insert_item(buffer_item item) {
    //插入产品
    buffer[out] = item;
    out = (out + 1) % BUFFER_SIZE;
    return 0;
}

//有限缓存删除--消费
int remove_item(buffer_item *item) {
    // 将buffer[in]移除，并将item填充进去
    *item = buffer[in];
    in = (in + 1) % BUFFER_SIZE;
    return 0;
}

//生产者
void *producer(void* param) {
    while (1){
        sem_wait(&empty);
        sem_wait(&mutex);
        //生产产品
        insert_item(id);
        sleep(5);
        printf("ThreadId %d : Producer produce productId -> %d \n", pthread_self(),id);
        id++;
        sem_post(&mutex);
        sem_post(&full);
    }
    pthread_exit(0);
}

//消费者
void *consumer(void* param) {
    while (1){
        sem_wait(&full);
        sem_wait(&mutex);
        //消费产品
        int item;
        remove_item(&item);
        sleep(3);
        printf("ThreadId %d : Consumer consume productId -> %d \n", pthread_self(),item);
        sem_post(&mutex);
        sem_post(&empty);
    }
    pthread_exit(0);
}
void getProperty(pthread_attr_t attr){
    int ret;
    //并发级别
    int level;
    ret = pthread_getconcurrency();
    if(0 != ret) {
        printf("error \n");
    } else {
        printf("线程并发级别为: %d\n", level);
    }
    //线程优先级
    int priority;
    ret = pthread_attr_getschedparam(&attr,&priority);
    if(0 != ret) {
        printf("error \n");
    } else {
        printf("线程优先级 : 优先级 %d\n", priority);
    }
    //线程的调度策略
    int policy;
    ret = pthread_attr_getschedpolicy(&attr, &policy);
    if(0 != ret) {
        printf("error\n");
    }
    else {
        if(SCHED_FIFO == policy)
            //先来先服务
            printf("线程调度策略: 先来先服务\n");
        else if(SCHED_RR == policy)
            //时间片轮转
            printf("线程调度策略: 时间片轮转\n");
        else if(SCHED_OTHER == policy)
            //其他
            printf("线程调度策略: 其他\n");
    }
    //线程栈大小
    size_t size;
    ret = pthread_attr_getstacksize(&attr, &size);
    if(0 != ret) {
        printf("error");
    } else {
        printf("线程栈大小: %lu\n", size);
    }
    //线程的作用域
    int scope;
    ret = pthread_attr_getscope(&attr, &scope);
    if(0 != ret) {
        printf("error");
    } else {
//        非绑定的
        if(PTHREAD_SCOPE_PROCESS == scope)
            printf("线程的作用域: PTHREAD_SCOPE_PROCESS\n");
        //绑定的线程  被绑定的线程具有较高的响应速度
        else if(PTHREAD_SCOPE_SYSTEM == scope)
            printf("线程的作用域: PTHREAD_SCOPE_SYSTEM\n");
    }
}

int main() {
    //线程id
    pthread_t tid[4];

    pthread_attr_t attr;
    pthread_attr_init(&attr);
    //设置调度方式为先来先服务
        pthread_attr_setschedpolicy(&attr,SCHED_FIFO);
//    对mutex进行初始化
    //第二个参数 不为０时此信号量在进程间共享，否则只能为当前进程的所有线程共享
    //第三个参数 给出了信号量的初始值。　　
    sem_init(&mutex, 0, 1);
    sem_init(&empty, 0, BUFFER_SIZE);
    sem_init(&full, 0, 0);
    in = out = 0;
    getProperty(attr);
    //两个生产者，两个消费者
    pthread_create(&tid[0], &attr ,consumer, NULL);
    pthread_create(&tid[1], &attr ,producer, NULL);
    pthread_create(&tid[2], &attr ,consumer, NULL);
    pthread_create(&tid[3], &attr, producer, NULL);
    char c;
    //用户输入q，结束进程
    if (scanf("%c",&c)=='q'){
        for (int i = 0; i < 4; ++i) {
            pthread_cancel(tid[i]);
        }
    }
    //释放信号量
    sem_destroy(&mutex);
    sem_destroy(&empty);
    sem_destroy(&full);
    return 0;
}

